import { GameSession, Position, SessionResult, ActionType, InventoryItem, Room, Enemy, Container } from '../types/game';
import { CITY_RUINS_MAP } from '../data/mapConfigs';
import { LootCalculator } from '../data/containerConfigs';
import { ItemManager } from './itemManager';

/**
 * 对局管理器
 * 处理游戏对局的逻辑，包括时间管理、位置移动、战斗、搜索等
 */
export class SessionManager {
  /**
   * 创建新的游戏对局
   */
  static createSession(
    selectedItems: InventoryItem[]
  ): GameSession {
    // 使用城市废墟地图，从默认开始区域开始
    const startingZone = CITY_RUINS_MAP.zones.find(zone => zone.id === CITY_RUINS_MAP.startingZone);
    if (!startingZone) {
      throw new Error(`Starting zone not found: ${CITY_RUINS_MAP.startingZone}`);
    }

    // 默认从第一个建筑的第一层第一个房间开始
    const firstBuilding = startingZone.buildings[0];
    const firstFloor = firstBuilding.floors[0];
    const firstRoom = firstFloor.rooms[0];

    const session: GameSession = {
      id: `session_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`,
      startTime: new Date(),
      remainingTime: 1800, // 30分钟 = 1800秒
      maxTime: 1800,
      currentPosition: {
        mapId: CITY_RUINS_MAP.id,
        zoneId: startingZone.id,
        buildingId: firstBuilding.id,
        floorId: firstFloor.id,
        roomId: firstRoom.id
      },
      broughtItems: [...selectedItems],
      foundItems: [],
      isActive: true,
      canExtract: false
    };

    return session;
  }

  /**
   * 执行行动
   */
  static executeAction(
    session: GameSession,
    actionType: ActionType,
    targetPosition?: Position,
    targetItem?: InventoryItem,
    targetEnemy?: Enemy
  ): {
    session: GameSession;
    result: 'continue' | 'timeout' | 'killed' | 'extracted';
    message: string;
    foundItems?: InventoryItem[];
  } {
    if (!session.isActive) {
      return {
        session,
        result: 'continue',
        message: '对局已结束'
      };
    }

    const updatedSession = { ...session };
    let message = '';
    let foundItems: InventoryItem[] = [];
    let result: 'continue' | 'timeout' | 'killed' | 'extracted' = 'continue';

    // 获取行动时间消耗
    const timeCosts = {
      [ActionType.MOVE]: 60,
      [ActionType.ZONE_TRAVEL]: 300,
      [ActionType.SEARCH]: 180,
      [ActionType.SEARCH_CONTAINER]: 0, // 容器搜索时间由容器类型决定
      [ActionType.ATTACK]: 120,
      [ActionType.HEAL]: 90,
      [ActionType.REST]: 300,
      [ActionType.EXTRACT]: 30
    };

    const timeCost = timeCosts[actionType];

    // 检查时间是否足够
    if (updatedSession.remainingTime < timeCost) {
      updatedSession.remainingTime = 0;
      updatedSession.isActive = false;
      return {
        session: updatedSession,
        result: 'timeout',
        message: '时间不足，对局失败！'
      };
    }

    // 执行具体行动
    switch (actionType) {
      case ActionType.MOVE:
        if (targetPosition) {
          updatedSession.currentPosition = targetPosition;
          updatedSession.canExtract = this.checkCanExtract(updatedSession);
          message = '已移动到新位置';
        }
        break;

      case ActionType.ZONE_TRAVEL:
        if (targetPosition) {
          updatedSession.currentPosition = targetPosition;
          updatedSession.canExtract = this.checkCanExtract(updatedSession);
          const targetZone = CITY_RUINS_MAP.zones.find(z => z.id === targetPosition.zoneId);
          message = `已移动到${targetZone?.name || '新区域'}`;
        }
        break;

      case ActionType.SEARCH:
        const searchResult = this.executeSearch(updatedSession);
        foundItems = searchResult.items;
        updatedSession.foundItems.push(...foundItems);
        message = searchResult.message;
        break;

      case ActionType.SEARCH_CONTAINER:
        // 容器搜索需要额外的参数，这里只是占位
        message = '需要指定要搜索的容器';
        break;

      case ActionType.ATTACK:
        if (targetEnemy) {
          const combatResult = this.executeCombat(updatedSession, targetEnemy);
          message = combatResult.message;
          if (combatResult.playerDefeated) {
            result = 'killed';
            updatedSession.isActive = false;
            return {
              session: updatedSession,
              result,
              message: '你被击败了，对局失败！'
            };
          }
          if (combatResult.lootItems) {
            foundItems = combatResult.lootItems;
            updatedSession.foundItems.push(...foundItems);
          }
        }
        break;

      case ActionType.HEAL:
        if (targetItem) {
          message = `使用了${targetItem.name}`;
          // 从携带物品中移除
          const itemIndex = updatedSession.broughtItems.findIndex(item => 
            item.instanceId === targetItem.instanceId
          );
          if (itemIndex !== -1) {
            updatedSession.broughtItems[itemIndex].quantity -= 1;
            if (updatedSession.broughtItems[itemIndex].quantity <= 0) {
              updatedSession.broughtItems.splice(itemIndex, 1);
            }
          }
        }
        break;

      case ActionType.REST:
        message = '你休息了一会儿，恢复了一些体力';
        break;

      case ActionType.EXTRACT:
        if (updatedSession.canExtract) {
          result = 'extracted';
          updatedSession.isActive = false;
          return {
            session: updatedSession,
            result,
            message: '成功撤离！',
            foundItems: updatedSession.foundItems
          };
        } else {
          message = '当前位置无法撤离！';
          // 不消耗时间
          return {
            session: updatedSession,
            result: 'continue',
            message,
            foundItems
          };
        }
    }

    // 扣除时间
    updatedSession.remainingTime -= timeCost;

    // 检查时间是否耗尽
    if (updatedSession.remainingTime <= 0) {
      updatedSession.remainingTime = 0;
      updatedSession.isActive = false;
      result = 'timeout';
      message = '时间耗尽，对局失败！';
    }

    return {
      session: updatedSession,
      result,
      message,
      foundItems
    };
  }

  /**
   * 获取当前房间信息
   */
  static getCurrentRoom(session: GameSession): Room | null {
    const zone = CITY_RUINS_MAP.zones.find(z => z.id === session.currentPosition.zoneId);
    if (!zone) return null;

    const building = zone.buildings.find(b => b.id === session.currentPosition.buildingId);
    if (!building) return null;

    const floor = building.floors.find(f => f.id === session.currentPosition.floorId);
    if (!floor) return null;

    const room = floor.rooms.find(r => r.id === session.currentPosition.roomId);
    return room || null;
  }

  /**
   * 获取可移动的房间列表
   */
  static getAvailableRooms(session: GameSession): Room[] {
    const zone = CITY_RUINS_MAP.zones.find(z => z.id === session.currentPosition.zoneId);
    if (!zone) return [];

    const allRooms: Room[] = [];
    
    zone.buildings.forEach(building => {
      building.floors.forEach(floor => {
        floor.rooms.forEach(room => {
          // 排除当前房间
          if (room.id !== session.currentPosition.roomId) {
            allRooms.push(room);
          }
        });
      });
    });

    return allRooms;
  }

  /**
   * 获取所有撤离点
   */
  static getExtractionPoints(): Position[] {
    const extractionPoints: Position[] = [];
    
    // 遍历所有区域查找撤离点
    CITY_RUINS_MAP.zones.forEach(zone => {
      zone.buildings.forEach(building => {
        building.floors.forEach(floor => {
          floor.rooms.forEach(room => {
            if (room.isExtractionPoint) {
              extractionPoints.push({
                mapId: CITY_RUINS_MAP.id,
                zoneId: zone.id,
                buildingId: building.id,
                floorId: floor.id,
                roomId: room.id
              });
            }
          });
        });
      });
    });

    return extractionPoints;
  }

  /**
   * 获取区域传送点
   */
  static getZoneTransitions(session: GameSession): { room: Room; targetZone: string }[] {
    const zone = CITY_RUINS_MAP.zones.find(z => z.id === session.currentPosition.zoneId);
    if (!zone) return [];

    const transitions: { room: Room; targetZone: string }[] = [];
    
    zone.buildings.forEach(building => {
      building.floors.forEach(floor => {
        floor.rooms.forEach(room => {
          if (room.isZoneTransition && room.connectedZone) {
            transitions.push({
              room,
              targetZone: room.connectedZone
            });
          }
        });
      });
    });

    return transitions;
  }

  /**
   * 获取当前房间的容器
   */
  static getRoomContainers(session: GameSession): Container[] {
    const currentRoom = this.getCurrentRoom(session);
    return currentRoom?.containers || [];
  }

  /**
   * 获取可搜索的容器（未搜索过的）
   */
  static getSearchableContainers(session: GameSession): Container[] {
    return this.getRoomContainers(session).filter(container => !container.searched);
  }

  /**
   * 检查是否可以撤离
   */
  private static checkCanExtract(session: GameSession): boolean {
    const currentRoom = this.getCurrentRoom(session);
    return currentRoom?.isExtractionPoint === true;
  }

  /**
   * 执行搜索
   */
  private static executeSearch(session: GameSession): {
    items: InventoryItem[];
    message: string;
  } {
    const currentRoom = this.getCurrentRoom(session);
    if (!currentRoom) {
      return {
        items: [],
        message: '无法在此位置搜索'
      };
    }

    if (currentRoom.searched) {
      return {
        items: [],
        message: '此房间已经搜索过了'
      };
    }

    if (!currentRoom.hasLoot) {
      currentRoom.searched = true;
      return {
        items: [],
        message: '搜索完成，但没有找到任何物品'
      };
    }

    let foundItems: InventoryItem[] = [];

    // 如果房间使用新的战利品表系统
    if (currentRoom.lootTableId) {
      const lootResults = LootCalculator.generateLoot(currentRoom.lootTableId);
      foundItems = lootResults.map(loot => {
        const item = ItemManager.createItem(loot.itemId, loot.quantity);
        return item;
      }).filter(item => item !== null) as InventoryItem[];
    }
    // 向后兼容：如果使用旧的直接物品列表
    else if (currentRoom.lootTable) {
      currentRoom.lootTable.forEach(itemId => {
        // 30%的几率找到每个物品
        if (Math.random() < 0.3) {
          const item = ItemManager.createItem(itemId, 1);
          if (item) {
            foundItems.push(item);
          }
        }
      });
    }

    currentRoom.searched = true;
    currentRoom.hasLoot = false;

    return {
      items: foundItems,
      message: foundItems.length > 0 
        ? `搜索露天区域完成！找到了 ${foundItems.length} 个物品：${foundItems.map(item => `${item.name} x${item.quantity}`).join(', ')}`
        : '搜索露天区域完成，但没有找到任何物品'
    };
  }

  /**
   * 执行容器搜索
   */
  static executeContainerSearch(
    session: GameSession, 
    containerId: string
  ): {
    session: GameSession;
    result: 'continue' | 'timeout' | 'killed' | 'extracted';
    message: string;
    foundItems?: InventoryItem[];
  } {
    const currentRoom = this.getCurrentRoom(session);
    if (!currentRoom || !currentRoom.containers) {
      return {
        session,
        result: 'continue',
        message: '无法在此位置搜索容器'
      };
    }

    const container = currentRoom.containers.find(c => c.id === containerId);
    if (!container) {
      return {
        session,
        result: 'continue',
        message: '找不到指定的容器'
      };
    }

    if (container.searched) {
      return {
        session,
        result: 'continue',
        message: '该容器已经被搜索过了'
      };
    }

    const containerType = LootCalculator.getContainerType(container.typeId);
    if (!containerType) {
      return {
        session,
        result: 'continue',
        message: '未知的容器类型'
      };
    }

    // 检查是否需要钥匙
    if (container.locked && container.requiredKey) {
      const hasKey = session.broughtItems.some(item => item.id === container.requiredKey) ||
                    session.foundItems.some(item => item.id === container.requiredKey);
      
      if (!hasKey) {
        return {
          session,
          result: 'continue',
          message: `该容器已锁定，需要 ${container.requiredKey} 才能打开`
        };
      }
    }

    // 检查时间是否足够
    const updatedSession = { ...session };
    if (updatedSession.remainingTime < containerType.searchTime) {
      updatedSession.remainingTime = 0;
      updatedSession.isActive = false;
      return {
        session: updatedSession,
        result: 'timeout',
        message: '时间不足，对局失败！'
      };
    }

    // 消耗时间
    updatedSession.remainingTime -= containerType.searchTime;

    // 生成战利品
    const lootResults = LootCalculator.generateLoot(containerType.lootTableId);
    const foundItems = lootResults.map(loot => {
      const item = ItemManager.createItem(loot.itemId, loot.quantity);
      return item;
    }).filter(item => item !== null) as InventoryItem[];

    // 标记容器为已搜索
    container.searched = true;

    // 添加到找到的物品中
    updatedSession.foundItems.push(...foundItems);

    const containerName = container.name || containerType.name;
    const message = foundItems.length > 0 
      ? `搜索${containerName}完成！找到了 ${foundItems.length} 个物品：${foundItems.map(item => `${item.name} x${item.quantity}`).join(', ')}`
      : `搜索${containerName}完成，但没有找到任何物品`;

    return {
      session: updatedSession,
      result: 'continue',
      message,
      foundItems
    };
  }

  /**
   * 执行战斗
   */
  private static executeCombat(_session: GameSession, enemy: Enemy): {
    message: string;
    playerDefeated: boolean;
    lootItems?: InventoryItem[];
  } {
    if (enemy.defeated) {
      return {
        message: '敌人已经被击败了',
        playerDefeated: false
      };
    }

    // 简化的战斗系统
    const playerAttack = 40; // 基础攻击力，后续可以从装备计算
    const enemyDefense = enemy.defense || 0;
    const damage = Math.max(1, playerAttack - enemyDefense);

    enemy.health -= damage;

    if (enemy.health <= 0) {
      enemy.defeated = true;
      
      // 掉落物品
      const lootItems: InventoryItem[] = [];
      enemy.lootTable.forEach(itemId => {
        // 50%的几率掉落每个物品
        if (Math.random() < 0.5) {
          const item = ItemManager.createItem(itemId, 1);
          if (item) {
            lootItems.push(item);
          }
        }
      });

      return {
        message: `击败了${enemy.name}！` + (lootItems.length > 0 ? ` 获得了 ${lootItems.map(item => item.name).join(', ')}` : ''),
        playerDefeated: false,
        lootItems: lootItems.length > 0 ? lootItems : undefined
      };
    }

    // 敌人反击
    const enemyAttack = enemy.attack || 20;
    const playerDefense = 10; // 基础防御力，后续可以从装备计算
    const enemyDamage = Math.max(1, enemyAttack - playerDefense);

    // 简化：假设玩家有100血，如果受到超过100伤害就死亡
    if (enemyDamage >= 100) {
      return {
        message: `${enemy.name}对你造成了致命伤害`,
        playerDefeated: true
      };
    }

    return {
      message: `对${enemy.name}造成了${damage}点伤害，${enemy.name}还剩${enemy.health}血量`,
      playerDefeated: false
    };
  }

  /**
   * 计算对局结果奖励
   */
  static calculateRewards(session: GameSession, result: SessionResult): {
    keptItems: InventoryItem[];
    lostItems: InventoryItem[];
    coinReward: number;
  } {
    if (result === SessionResult.SUCCESS) {
      // 成功撤离：保留所有物品，获得奖励金币
      const allItems = [...session.broughtItems, ...session.foundItems];
      return {
        keptItems: allItems,
        lostItems: [],
        coinReward: Math.floor(session.foundItems.length * 50) // 每个找到的物品奖励50金币
      };
    } else {
      // 失败：失去所有物品
      return {
        keptItems: [],
        lostItems: [...session.broughtItems, ...session.foundItems],
        coinReward: 0
      };
    }
  }

  /**
   * 格式化时间显示
   */
  static formatTime(seconds: number): string {
    const minutes = Math.floor(seconds / 60);
    const remainingSeconds = seconds % 60;
    return `${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`;
  }

  /**
   * 获取位置描述
   */
  static getLocationDescription(position: Position): string {
    const zone = CITY_RUINS_MAP.zones.find(z => z.id === position.zoneId);
    if (!zone) return '未知位置';

    const building = zone.buildings.find(b => b.id === position.buildingId);
    if (!building) return zone.name;

    const floor = building.floors.find(f => f.id === position.floorId);
    if (!floor) return `${zone.name} - ${building.name}`;

    const room = floor.rooms.find(r => r.id === position.roomId);
    if (!room) return `${zone.name} - ${building.name} - ${floor.name}`;

    return `${zone.name} - ${building.name} - ${floor.name} - ${room.name}`;
  }
}